<script setup lang="ts">
import { ref, watch, onMounted, onUnmounted, nextTick } from 'vue'
import { useThrottleFn } from '@vueuse/core'

export interface InfiniteScrollProps<T> {
  loader: (page: number) => Promise<T[]>
  itemHeight: number
  gap?: number
  initialPage?: number
  pageSize?: number
}

const props = withDefaults(defineProps<InfiniteScrollProps<any>>(), {
  gap: 0,
  initialPage: 1,
  pageSize: 20
})

const emit = defineEmits(['update:loading', 'update:finished'])

// 组件状态
const list = ref<any[]>([])
const currentPage = ref(props.initialPage)
const loading = ref(false)
const finished = ref(false)
const error = ref<Error | null>(null)
const scrollContainer = ref<HTMLElement | null>(null)

// 监听 initialPage 变化
watch(
  () => props.initialPage,
  (newVal) => {
    console.log('[VirtualList] 同步页码:', newVal)
    currentPage.value = newVal
  },
  { immediate: true }
)

// 重置逻辑
const reset = () => {
  console.log('[VirtualList] 执行重置', {
    initialPage: props.initialPage,
    currentPage: currentPage.value
  })
  
  list.value = []
  currentPage.value = props.initialPage
  finished.value = false
  loading.value = false
  error.value = null
  
  nextTick(() => {
    scrollContainer.value?.scrollTo(0, 0)
    console.log('[VirtualList] 滚动位置已重置')
  })
}

// 加载更多逻辑
// 跟踪滚动速度
let lastScrollTop = 0
let lastScrollTime = Date.now()
let scrollVelocity = 0

const checkLoadMore = useThrottleFn(async () => {
  if (loading.value || finished.value) return

  const container = scrollContainer.value
  if (!container) return

  // 计算滚动速度
  const now = Date.now()
  const deltaTime = now - lastScrollTime
  const deltaY = container.scrollTop - lastScrollTop
  scrollVelocity = deltaY / deltaTime
  
  lastScrollTop = container.scrollTop
  lastScrollTime = now

  // 动态计算触发位置，添加缓冲区和速度补偿
  const lastItemPos = (list.value.length * props.itemHeight) 
    + ((list.value.length - 1) * props.gap)
    - (props.itemHeight * 1.5) // 增加缓冲区
  
  // 根据滚动速度调整触发位置
  const velocityOffset = Math.min(Math.max(scrollVelocity * 50, 0), props.itemHeight * 2)
  const triggerPos = container.scrollTop + container.clientHeight + velocityOffset
  
  console.log('[VirtualList] 位置检查', {
    scrollTop: container.scrollTop,
    clientHeight: container.clientHeight,
    lastItemPos,
    triggerPos,
    scrollVelocity,
    velocityOffset
  })
  
  if (triggerPos >= lastItemPos) {
    console.log('[VirtualList] 触发加载')
    try {
      loading.value = true
      emit('update:loading', true)
      
      const newItems = await props.loader(currentPage.value)
      console.log('[VirtualList] 加载完成', newItems)
      
      list.value = [...list.value, ...newItems]
      
      if (newItems.length < props.pageSize) {
        finished.value = true
        emit('update:finished', true)
      }
      
      currentPage.value++
    } catch (err) {
      error.value = err as Error
    } finally {
      loading.value = false
      emit('update:loading', false)
    }
  }
}, 100) // 减少节流时间

// 挂载/卸载事件监听
onMounted(() => {
  scrollContainer.value?.addEventListener('scroll', checkLoadMore)
  checkLoadMore() // 初始加载
})

onUnmounted(() => {
  scrollContainer.value?.removeEventListener('scroll', checkLoadMore)
})

// 暴露方法
defineExpose({
  reset,
  loadMore: checkLoadMore
})
</script>

<template>
  <div
    ref="scrollContainer"
    class="infinite-scroll-container"
    :style="{ height: '100%', overflowY: 'auto' }"
  >
    <!-- 调试信息 -->
    <div class="debug-info fixed right-2 top-2 bg-black/50 text-white p-2 text-xs">
      <div>当前页码: {{ currentPage }}</div>
      <div>加载状态: {{ loading }}</div>
      <div>完成状态: {{ finished }}</div>
      <div>列表长度: {{ list.length }}</div>
    </div>

    <!-- 虚拟列表 -->
    <div 
      class="virtual-list" 
      :style="{ height: `${list.length * itemHeight + (list.length - 1) * gap}px` }"
    >
      <div
        v-for="(item, index) in list"
        :key="index"
        class="list-item"
        :style="{
          height: `${itemHeight}px`,
          transform: `translateY(${index * (itemHeight + gap)}px)`
        }"
      >
        <slot :item="item" :index="index" />
      </div>
    </div>

    <!-- 加载状态 -->
    <div v-if="loading" class="loading-state">
      <slot name="loading">
        <div class="default-loading">加载中...</div>
      </slot>
    </div>

    <!-- 完成状态 -->
    <div v-if="finished" class="finished-state">
      <slot name="finished">
        <div class="default-finished">没有更多数据了</div>
      </slot>
    </div>

    <!-- 错误状态 -->
    <div v-if="error" class="error-state">
      <slot name="error" :error="error">
        <div class="default-error">
          加载失败: {{ error.message }}
          <button @click="checkLoadMore">重试</button>
        </div>
      </slot>
    </div>
  </div>
</template>

<style scoped>
.infinite-scroll-container {
  position: relative;
  overflow-anchor: none;
}

.virtual-list {
  position: relative;
}

.list-item {
  position: absolute;
  width: 100%;
  box-sizing: border-box;
  contain: strict;
}

.loading-state,
.finished-state,
.error-state {
  padding: 16px;
  text-align: center;
  color: #666;
}

.default-error {
  color: #ff4444;
}

.default-error button {
  margin-left: 8px;
  padding: 4px 12px;
  background: #eee;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.debug-info {
  z-index: 100;
  border-radius: 4px;
}
</style>
